package com.cskaoyan.gateway.controller.promotion;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cskaoyan.gateway.cache.CacheManager;
import com.google.common.util.concurrent.RateLimiter;
import com.mall.commons.result.ResponseData;
import com.mall.commons.result.ResponseUtil;
import com.mall.commons.tool.utils.UtilDate;
import com.mall.promo.PromoService;
import com.mall.promo.constant.PromoRetCode;
import com.mall.promo.dto.*;
import com.mall.user.annotation.Anoymous;
import com.mall.user.intercepter.TokenIntercepter;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Description: 秒杀模块
 * @Author: 徐能雄
 * @Date: 2021/10/6 15:01
 */
@RestController
@RequestMapping("/shopping")
@Slf4j
public class PromotionController {

    @Reference(timeout = 30000, check = false)
    PromoService promoService;

    @Autowired
    CacheManager cacheManager;

    // 令牌桶
    RateLimiter rateLimiter;

    ExecutorService threadPool;

    @PostConstruct
    public void init() {
        // 创建一个令牌桶，每秒有100个令牌的令牌桶
        rateLimiter = RateLimiter.create(100);

        threadPool = Executors.newFixedThreadPool(100);
    }

    /**
     * 1、获取秒杀商品列表接口
     */
    @GetMapping("/seckilllist")
    @Anoymous
    public ResponseData seckillList(Integer sessionId){

        PromoInfoRequest promoInfoRequest = new PromoInfoRequest();
        promoInfoRequest.setSessionId(sessionId);
        //获取年月日的时间信息
        promoInfoRequest.setYyyymmdd(UtilDate.getDate());

        PromoInfoResponse promoInfoResponse = promoService.getPromoList(promoInfoRequest);
        if (PromoRetCode.SUCCESS.getCode().equals(promoInfoResponse.getCode())){
            return new ResponseUtil<>().setData(promoInfoResponse);
        }else {
            return new ResponseUtil<>().setErrorMsg(promoInfoResponse.getMsg());
        }
    }

    /**
     * 2、获取秒杀商品详情接⼝
     */
    @PostMapping("/promoProductDetail")
    public ResponseData promoProductDetail(@RequestBody PromoProductDetailRequest request){

        PromoProductDetailResponse promoProductDetailResponse = promoService.getPromoProductDetail(request);
        if (PromoRetCode.SUCCESS.getCode().equals(promoProductDetailResponse.getCode())){
            return new ResponseUtil<>().setData(promoProductDetailResponse);
        }else {
            return new ResponseUtil<>().setErrorMsg(promoProductDetailResponse.getMsg());
        }
    }

    /**
     * 3、秒杀下单接⼝(⽣成订单、扣减库存、⽣成商品的邮寄信息)
     */
    @PostMapping("/seckill")
    public ResponseData seckill(@RequestBody CreatePromoOrderRequest request, HttpServletRequest httpServletRequest){

        // 利用令牌桶，进行总体流量的限流
        // acquire 方法的作用，从令牌桶中获取一个令牌
        // 如果获取令牌失败，当前线程会被阻塞
        rateLimiter.acquire();

//        // 业务限流: 判断商品售罄标志
//        Long productId = request.getProductId();
//        Long psId = request.getPsId();
//        String key = "promo_product_not_engough_" + productId + "_" + psId;
//
//        String stockResult = cacheManager.checkCache(key);
//        if (stockResult != null && "none".equals(stockResult.trim())) {
//            // 直接返回秒杀失败的响应即可
//            // return
//        }


        log.info("shopping/seckill start");
        String attribute = (String) httpServletRequest.getAttribute(TokenIntercepter.USER_INFO_KEY);
        JSONObject jsonObject = JSON.parseObject(attribute);
        Long uid = Long.parseLong(jsonObject.get("uid").toString());

        request.setUserId(uid);

        //CreatePromoOrderResponse createPromoOrderResponse = promoService.createPromoOrder(request);
        CreatePromoOrderResponse createPromoOrderResponse = promoService.createPromoOrderInTransaction(request);
        if (PromoRetCode.SUCCESS.getCode().equals(createPromoOrderResponse.getCode())){
            return new ResponseUtil<>().setData(createPromoOrderResponse);
        }else {
            return new ResponseUtil<>().setErrorMsg(createPromoOrderResponse.getMsg());
        }
    }



}
